/*
 * OpenListener.java
 *
 * Created on Aug 18, 2007, 8:21:38 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.usixml.model.client;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.iknowu.util.Tree;
import org.iknowu.util.TreeNode;
import org.usixml.model.client.ui.MainWindow;
import org.usixml.model.imports.businessprocess.BusinessProcess;
import org.usixml.model.imports.businessprocess.BusinessProcessElement;

/**
 *
 * @author htmfilho
 */
public class OpenListener implements ActionListener {
    
    private JFileChooser fcExternalModelFile;
    private MainWindow mainWindow;
    private BusinessProcess businessProcess;
    
    private BusinessProcessElement activity;
    private List<TreeNode> activities;
    
    public OpenListener(MainWindow mainWindow) {
        this.mainWindow = mainWindow;
        fcExternalModelFile = new JFileChooser();
        fcExternalModelFile.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fcExternalModelFile.addChoosableFileFilter(new ExternalModelFileFilter());
        fcExternalModelFile.setAcceptAllFileFilterUsed(false);
    }
    
    public BusinessProcess getBusinessProcess() {
        return businessProcess;
    }
    
    public void actionPerformed(ActionEvent e) {
        int returnVal = fcExternalModelFile.showOpenDialog(mainWindow);
        
        if(returnVal == JFileChooser.APPROVE_OPTION) {
            InputStreamReader reader = null;
            try {
                activity = null;
                activities = null;
                
                // Exploring the XML file.
                XMLInputFactory factory = XMLInputFactory.newInstance();
                InputStream is = new FileInputStream(fcExternalModelFile.getSelectedFile());
                reader = new InputStreamReader(is, Charset.forName("UTF-16"));
                XMLStreamReader xmlr = factory.createXMLStreamReader(reader);
                while(xmlr.hasNext()) {
                    processEvent(xmlr);
                    xmlr.next();
                }
                
                // Building a tree from the list of activities.
                Tree elements = new Tree();
                elements.put(activities);
                
                // Keeping the loaded data for manipulation.
                businessProcess = new BusinessProcess("Provision Business Process");
                businessProcess.setElements(elements);
                
                DefaultMutableTreeNode root = new DefaultMutableTreeNode(businessProcess);
                                
                List roots = elements.getRoots();
                TreeNode r = null;
                for(int i = 0;i < roots.size();i++) {
                    r = (TreeNode)roots.get(i);
                    root.add(addBusinessProcessElement(r));
                }
                JTree treProcessStructure = new JTree(root);
                mainWindow.setTreProcessStructure(treProcessStructure);
            } 
            catch (XMLStreamException ex) {
                Logger.getLogger("global").log(Level.SEVERE, ex.getMessage(), ex);
            } 
            catch (FileNotFoundException ex) {
                Logger.getLogger("global").log(Level.SEVERE, ex.getMessage(), ex);
            } 
            finally {
                try {
                    reader.close();
                } 
                catch (IOException ex) {
                    Logger.getLogger("global").log(Level.SEVERE, ex.getMessage(), ex);
                }
            }
        }
    }
    
    private void processEvent(XMLStreamReader xmlr) throws XMLStreamException {
        switch (xmlr.getEventType()) {
            case XMLStreamConstants.START_ELEMENT :
                if(xmlr.hasName()) {
                    String tagName = xmlr.getLocalName();
                    if(tagName.equals("businessDomain") || tagName.equals("businessProcess") || tagName.equals("activityCore")) {
                        activity = new BusinessProcessElement();
                        activity.setId(xmlr.getAttributeValue(0));
                        activity.setName(xmlr.getAttributeValue(1));
                    }
                    else if (tagName.equals("modifyTime") && activity != null)
                        activity.setModified(xmlr.getElementText());
                    else if (tagName.equals("description") && activity != null)
                        activity.setDescription(xmlr.getElementText());
                    else if (tagName.equals("stereotype") && activity != null)
                        activity.setStereotype(xmlr.getElementText());
                    else if (tagName.equals("parent") && activity != null) {
                        String parentId = xmlr.getAttributeValue(0);
                        if(parentId.length() > 0) {
                            BusinessProcessElement parent = new BusinessProcessElement(parentId);
                            activity.setSuperNode(parent);
                        }
                    }
                }
                break;
            case XMLStreamConstants.END_ELEMENT :
                if(xmlr.hasName()) {
                    String tagName = xmlr.getLocalName();
                    if(tagName.equals("businessDomain") || tagName.equals("businessProcess")) {
                        if(activities == null)
                            activities = new ArrayList<TreeNode>();
                        activities.add(activity);
                        activity = null;
                    }
                    else if(tagName.equals("activityCore")) {
                        if(activities == null)
                            activities = new ArrayList<TreeNode>();
                        if(activity.getSuperNode() != null)
                            activities.add(activity);
                        activity = null;
                    }
                }
                break;
        }
    }
    
    private DefaultMutableTreeNode addBusinessProcessElement(TreeNode treeNode) {
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(treeNode);
        List subNodes = treeNode.getSubNodes();
        if(subNodes != null) {
            TreeNode subNode;
            for(int i = 0;i < subNodes.size();i++) {
                subNode = (TreeNode)subNodes.get(i);
                node.add(addBusinessProcessElement(subNode));
            }
        }
        return node;
    }
}